<template>
  <layoutHeader></layoutHeader>
  <div>
    <div class="all">
      <video class="video" ref="localCameraVideo"></video>
      <video class="video" ref="remoteCameraVideo"></video>
      <div v-if="isRoomBusy">工作人员繁忙或不在线，请稍后再试!!!</div>
    </div>
    <div class="buttons">
      <button v-if="!calling && !communicating && !isRoomBusy" class="button" @click="upVideo">拨打</button>
      <button v-if="calling && called" class="button" @click="yesVideo">接听</button>
      <button v-if="communicating || calling" class="button" @click="downVideo">挂断</button>
    </div>
  </div>
  <layoutFooter></layoutFooter>
</template>

<script setup name="useProTable">
import { onMounted, ref } from "vue";
import { usePhoneStore } from "@/stores/phone.js";

const roomId = ref(); //房间号
const localCameraVideo = ref(); //自己的媒体
const remoteCameraVideo = ref(); //别人的媒体
const called = ref(false); //是否是接收方
const caller = ref(false); //是否是发起方
const calling = ref(false); //呼叫中
const communicating = ref(false); //视频通话中
const peer = ref();
const localStream = ref();
const isRoomBusy = ref(false);
const userId = ref();
let socket;

onMounted(() => {
  creatSocket();
});

//建立websocket
async function creatSocket() {
  const phoneStore = usePhoneStore();
  userId.value = BigInt(phoneStore.phone);
  socket = new WebSocket(`wss://192.168.58.147:8443/websocket/${userId.value}`);
  socket.onopen = function () {
    console.log("websocket打开");
    roomId.value = "0";
    socket.send(
      JSON.stringify({
        type: "joinRoom",
        roomId: roomId.value
      })
    );
  };
  socket.addEventListener("message", async message => {
    const dataJson = JSON.parse(message.data);
    // 处理接收到的消息

    //用户收到自己被分配的房间号，如果没被分配，则是0,提示工作人员繁忙请稍后再试
    if (dataJson.type == "getRoomId") {
      console.log(dataJson);
      if (dataJson.roomId == "0") isRoomBusy.value = true;
      else roomId.value = BigInt(dataJson.roomId);
    }
    //被呼叫方 接收到 呼叫方 请求通话的消息
    if (dataJson.type == "callRemote" && !caller.value) {
      //不是呼叫方
      console.log("被呼叫方 接收到 呼叫方 请求通话的消息");

      called.value = true;
      calling.value = true;
    }
    //呼叫方 接收到 被呼叫方 同意通话的消息，发送offer等验证信息
    if (dataJson.type == "acceptCall" && caller.value) {
      //是呼叫方
      console.log("呼叫方 接收到 被呼叫方 同意通话的消息");
      peer.value = new RTCPeerConnection();
      peer.value.addStream(localStream.value);

      //获取candidate信息
      peer.value.onicecandidate = event => {
        if (event.candidate) {
          socket.send(
            JSON.stringify({
              type: "sendCandidate",
              roomId: roomId.value,
              candidate: event.candidate,
              role: "caller"
            })
          );
        }
      };

      //获取对方的音视频流
      peer.value.onaddstream = async event => {
        communicating.value = true;
        calling.value = false;
        remoteCameraVideo.value.srcObject = event.stream;
        await remoteCameraVideo.value.play();
      };
      //获取自己的offer
      const offer = await peer.value.createOffer({
        offerToReceiveAudio: 1,
        offerToReceiveVideo: 1
      });
      //在本地设置offer信息
      await peer.value.setLocalDescription(offer);
      //发送offer
      socket.send(
        JSON.stringify({
          type: "sendOffer",
          roomId: roomId.value,
          offer: offer
        })
      );
    }
    //被呼叫方 接收到 呼叫方 发来的offer，回发answer等信息。
    if (dataJson.type == "sendOffer" && !caller.value) {
      //不是呼叫方
      console.log("被呼叫方 接收到 呼叫方 发来的offer");
      peer.value = new RTCPeerConnection();
      //添加本地音视频流
      await getUserMedia({ audio: true, video: true }).then(userMedia => {
        localCameraVideo.value.srcObject = userMedia;
        localCameraVideo.value.play();
        peer.value.addStream(userMedia);
      });

      //获取对方的音视频流
      peer.value.onaddstream = async event => {
        communicating.value = true;
        calling.value = false;
        remoteCameraVideo.value.srcObject = event.stream;
        await remoteCameraVideo.value.play();
      };

      //设置远端描述信息
      await peer.value.setRemoteDescription(dataJson.offer).then(() => {
        //获取candidate信息
        peer.value.onicecandidate = event => {
          if (event.candidate) {
            socket.send(
              JSON.stringify({
                type: "sendCandidate",
                roomId: roomId.value,
                candidate: event.candidate,
                role: "called"
              })
            );
          }
        };
      });

      //生成answer
      const answer = await peer.value.createAnswer();
      //在本地设置answer信息
      await peer.value.setLocalDescription(answer);
      //发送answer
      socket.send(
        JSON.stringify({
          type: "sendAnswer",
          roomId: roomId.value,
          answer: answer
        })
      );
    }
    //呼叫方 接收到 被呼叫方 发来的answer等信息，设置远端描述
    if (dataJson.type == "sendAnswer" && caller.value) {
      //是呼叫方
      console.log("呼叫方 接收到 被呼叫方 发来的answer");
      await peer.value.setRemoteDescription(dataJson.answer);
    }
    //当双方收到对方发来的candidate信息时，调用addIceCandidate()
    if (dataJson.type == "sendCandidate") {
      if ((caller.value && dataJson.role == "called") || (called.value && dataJson.role == "caller")) {
        console.log("接收到 对方 发来的candidate");
        try {
          await peer.value.addIceCandidate(dataJson.candidate);
        } catch (error) {
          console.log("未能设置远端描述");
        }
      }
    }
    //一方收到对方发来的挂断消息
    if (dataJson.type == "hangUp") {
      //被挂断的
      if (communicating.value) {
        //如果是通话中被挂断的
        console.log("接收到 对方 发来的挂断消息");
        communicating.value = false;
        if (caller.value) caller.value = false;
        if (called.value) called.value = false;

        // 关闭 RTCPeerConnection
        if (peer.value) {
          peer.value.close();
          peer.value = null;
        }

        // 停止所有媒体轨道
        if (localStream.value) {
          localStream.value.getTracks().forEach(track => track.stop());
          localStream.value = null;
        }
        if (localCameraVideo.value) {
          const tracks = localCameraVideo.value.srcObject.getTracks();
          tracks.forEach(track => track.stop());
          localCameraVideo.value.srcObject = null;
        }
        if (remoteCameraVideo.value) {
          const tracks = remoteCameraVideo.value.srcObject.getTracks();
          tracks.forEach(track => track.stop());
          remoteCameraVideo.value.srcObject = null;
        }
      } else if (called.value) {
        console.log("接收到 对方 发来的挂断消息");
        called.value = false;
        calling.value = false;
      } else if (caller.value) {
        console.log("接收到 对方 发来的挂断消息");
        caller.value = false;
        calling.value = false;

        if (localStream.value) {
          localStream.value.getTracks().forEach(track => track.stop());
          localStream.value = null;
        }

        if (localCameraVideo.value.srcObject) {
          const tracks = localCameraVideo.value.srcObject.getTracks();
          tracks.forEach(track => track.stop());
          localCameraVideo.value.srcObject = null;
        }
      }
    }
  });
  socket.onclose = function () {
    roomId.value = "0";
    console.log("websocket关闭");
  };
}
//获取媒体信息
async function getUserMedia(constraints) {
  try {
    if (window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia) {
      return await window.navigator.mediaDevices.getUserMedia(constraints);
    } else if (window.navigator.webkitGetUserMedia) {
      return await window.navigator.webkitGetUserMedia(constraints);
    } else if (window.navigator.mozGetUserMedia) {
      return await window.navigator.mozGetUserMedia(constraints);
    } else if (window.navigator.getUserMedia) {
      return await window.navigator.getUserMedia(constraints);
    } else {
      throw new Error("getUserMedia is not supported in this browser");
    }
  } catch (error) {
    console.error("Error accessing media devices.", error);
    throw error;
  }
}

//发起视频
const upVideo = async () => {
  caller.value = true;
  calling.value = true;
  socket.send(
    JSON.stringify({
      type: "callRemote",
      roomId: roomId.value
    })
  );
  await getUserMedia({ audio: true, video: true }).then(userMedia => {
    localStream.value = userMedia;
    localCameraVideo.value.srcObject = userMedia;
    localCameraVideo.value.play();
  });
};

//同意通话
const yesVideo = () => {
  socket.send(
    JSON.stringify({
      type: "acceptCall",
      roomId: roomId.value
    })
  );
};

//挂断通话
const downVideo = () => {
  caller.value = false;
  calling.value = false;
  communicating.value = false;
  if (caller.value) caller.value = false;
  if (called.value) called.value = false;
  socket.send(
    JSON.stringify({
      type: "hangUp",
      roomId: roomId.value
    })
  );

  // 关闭 RTCPeerConnection
  if (peer.value) {
    peer.value.close();
    peer.value = null;
  }

  // 停止所有媒体轨道
  if (localStream.value) {
    localStream.value.getTracks().forEach(track => track.stop());
    localStream.value = null;
  }

  if (localCameraVideo.value.srcObject) {
    const tracks = localCameraVideo.value.srcObject.getTracks();
    tracks.forEach(track => track.stop());
    localCameraVideo.value.srcObject = null;
  }

  if (remoteCameraVideo.value.srcObject) {
    const tracks = remoteCameraVideo.value.srcObject.getTracks();
    tracks.forEach(track => track.stop());
    remoteCameraVideo.value.srcObject = null;
  }
};
</script>

<style>
.all {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 360px;
  height: 480px;
  background-color: blue;
  transform: translate(-50%, -50%);
}
.buttons {
  position: absolute;
  top: 600px;
  left: 50%;
  display: flex;
  gap: 10px;
  transform: translateX(-50%);
}
.button {
  padding: 10px 20px;
  color: rgb(255 255 255);
  cursor: pointer;
  background-color: rgb(30 158 167);
  border: none;
  border-radius: 5px;
}
.video {
  width: 360px;
  height: 173px;
  margin-top: 30px;
  background-color: #4caf50;
}
</style>
